#pragma once
// 适配用户请求,定制通信协议字段
// 正确的调用compile and Run
// 形成唯一文件名

#include "compiler.hpp"
#include "runner.hpp"
#include <jsoncpp/json/json.h>
#include <signal.h>
#include<unistd.h>
namespace ns_compiler_and_run
{
   using namespace ns_compiler;
   using namespace ns_runner;
   using namespace ns_log;
   using namespace ns_util;

   class CompileAndRun
   {
   public:
      /*
       code>0 : 进程收到信号异常崩溃
       code<0 : 非运行错误(代码为空,编译报错......)
       code=0 : 整个过程全部完成
      */
      // 把code转为文字描述
      static std::string CodeToDesc(int code,const std::string &file_name)
      {
         std::string desc;
         switch (code)
         {
         case 0:
            desc = "编译运行成功";
            break;
         case -1:
            desc = "提交的代码是空";
            break;
         case -2:
            desc = "未知错误";
            break;
         case -3:
            FileUtil::ReadFile(PathUtil::CompilerError(file_name),&desc,true);
            break;
         case SIGABRT: // 6
            desc = "内存超过范围";
             break;
         case SIGXCPU: // 24
            desc = "CPU使用超时";
            break;
         case SIGFPE: // 8
            desc = "浮点数溢出";
            break;
         default:
            desc = "未知" + std::to_string(code);
            break;
         }
         return desc;
      }

      static void RemoveTempFile(const std::string& file_name)
      {
         std::string _src=PathUtil::Src(file_name);
         if(FileUtil::IsFileExists(_src))
         {
            unlink(_src.c_str());//删除文件
         }
         std::string _compiler_error=PathUtil::CompilerError(file_name);
         if(FileUtil::IsFileExists(_compiler_error))
         {
            unlink(_compiler_error.c_str());//删除文件
         }
         std::string _execute=PathUtil::Exe(file_name);
         if(FileUtil::IsFileExists(_execute))
         {
            unlink(_execute.c_str());//删除文件
         }

         std::string _stdin=PathUtil::Stdin(file_name);
         if(FileUtil::IsFileExists(_stdin))
         {
            unlink(_stdin.c_str());//删除文件
         }
         std::string _stdout=PathUtil::Stdout(file_name);
         if(FileUtil::IsFileExists(_stdout))
         {
            unlink(_stdout.c_str());//删除文件
         }
         std::string _stderr=PathUtil::Stderr(file_name);
         if(FileUtil::IsFileExists(_stderr))
         {
            unlink(_stderr.c_str());//删除文件
         }
      }
      /*****************************************************
      *输入:
         1.用户提交的代码
         2.用户提交代码对应的输入
         3.cpu_limit  men_limit
      *输出:
         1.status状态码
         2.请求结果
         3.选填:
            stdout:程序运行完的结果 stderr:程序运行完错误的结果
      ******************************************************/
      static void Start(const std::string &in_json, std::string *out_json)
      {
         Json::Value in_value;
         Json::Reader reader;
         reader.parse(in_json, in_value) ;// 反序列化 (解析谁,解析到哪)
             // in_json{"code","#include--","input","cpu_limit","men_limit"};
             // out_json{"status","reason","stdout","stderr",""};

         std::string code = in_value["code"].asString();
         std::string input = in_value["input"].asString();
         int cpu_limit = in_value["cpu_limit"].asInt();
         int mem_limit = in_value["mem_limit"].asInt();

         int status_code = 0;
         int ret_run = 0;
        
         std::string file_name = FileUtil::UniqFileName();
         Json::Value out_value;

         if (code.size() == 0) // 空代码
         {
            status_code = -1; // 代码为空
            goto END;
         }

         // 形成临时的src文件
         if (!FileUtil::WriteFile(PathUtil::Src(file_name), code))
         {
            status_code = -2; // 未知错误
            goto END;
         }

         // 编译文件
         if (!Compiler::Compile(file_name))
         {
            status_code = -3; // 编译失败
            goto END;
         }

         // 运行文件
         ret_run = Runner::Run(file_name, cpu_limit, mem_limit);

         if (ret_run < 0) // 内部错误
         {
            status_code = -2; // 未知错误
         }

         else if (ret_run > 0)
         {
            status_code = ret_run; // 程序崩溃了
         }
         else
         {
            // 运行成功
            status_code = 0;
         }
      END:
         out_value["status"] = status_code;
         out_value["reason"] = CodeToDesc(status_code,file_name);
         if (status_code == 0)
         {
            // 整个过程成功
            std::string _stdout;
            // 运行完后结果会写入Stdout中然后用ReadFile读取
            FileUtil::ReadFile(PathUtil::Stdout(file_name),&_stdout,true);
            out_value["stdout"] =_stdout;

            std::string _stderr;
            FileUtil::ReadFile(PathUtil::Stderr(file_name),&_stderr,true);
            out_value["stderr"] =_stderr;
         }

         // 序列化
         Json::StyledWriter writer;
         *out_json = writer.write(out_value);

         RemoveTempFile(file_name);//清理临时文件
      }
   };
}

